/**
 *  @file    CircleQueue.c
 *  @brief   顺序循环队列的基本操作实现
 *  @details 演示：
 *           1) 循环队列的初始化、入队、出队、查看队头
 *           2) 队列判满 / 判空（使用 % 模拟环形结构）
 *           3) 支持清空、打印等功能
 *           4) 空间复用、避免“假溢出”
 *  @author  WangBlue (wangjiping596@gmail.com)
 *  @date    2025-07-29 14:10
 *  @version 1.0
 */

#include <stdio.h>
#include <stdbool.h>

// ------------------------- 类型定义与常量 -------------------------

#define MAX_SIZE 5             ///< 循环队列容量（注意：最多只能存 MAX_SIZE-1 个元素）
typedef int EleType;           ///< 队列中元素类型

/**
 * @brief 循环队列结构体定义
 */
typedef struct circleQueue {
    EleType data[MAX_SIZE];    ///< 固定大小数组模拟环形队列
    int front, rear;           ///< 队头、队尾指针（逻辑环）
} circleQueue;

// ------------------------- 队列初始化 -------------------------

/**
 * @brief 初始化循环队列
 * @param q 指向队列的指针
 * @note  front = rear = 0 表示队列为空
 */
void initCircleQueue(circleQueue *q) {
    q->front = 0;
    q->rear = 0;
    for (int i = 0; i < MAX_SIZE; i++) {
        q->data[i] = 0;
    }
}

// ------------------------- 判满判空 -------------------------

/**
 * @brief 判断循环队列是否已满
 * @param q 指向队列的指针
 * @retval true  队满（留出一个空位区分满/空）
 * @retval false 队列未满
 */
bool isFill(circleQueue *q) {
    return (q->rear + 1) % MAX_SIZE == q->front;
}

/**
 * @brief 判断循环队列是否为空
 * @param q 指向队列的指针
 * @retval true  队列为空
 * @retval false 队列非空
 */
bool isEmpty(circleQueue *q) {
    return q->rear == q->front;
}

// ------------------------- 入队操作 -------------------------

/**
 * @brief 元素入队（从队尾插入）
 * @param q     指向队列的指针
 * @param value 要插入的元素值
 * @note 若队列已满，则不执行任何操作
 */
void inQueue(circleQueue *q, int value) {
    if (isFill(q)) return;
    q->data[q->rear] = value;
    q->rear = (q->rear + 1) % MAX_SIZE;
}

// ------------------------- 出队操作 -------------------------

/**
 * @brief 元素出队（从队头删除）
 * @param q     指向队列的指针
 * @param value 用于接收出队元素的变量地址
 * @note 若队列为空，则不执行任何操作
 */
void deQueue(circleQueue *q, int *value) {
    if (isEmpty(q)) return;
    *value = q->data[q->front];
    q->front = (q->front + 1) % MAX_SIZE;
}

// ------------------------- 查看队头 -------------------------

/**
 * @brief 查看队头元素（不出队）
 * @param q     指向队列的指针
 * @param value 用于接收队头值的变量地址
 * @note 若队列为空，则不执行任何操作
 */
void peek(circleQueue *q, int *value) {
    if (isEmpty(q)) return;
    *value = q->data[q->front];
}

// ------------------------- 清空队列 -------------------------

/**
 * @brief 清空队列内容（复位 front 和 rear）
 * @param q 指向队列的指针
 */
void clearQueue(circleQueue *q) {
    q->front = 0;
    q->rear = 0;
    for (int i = 0; i < MAX_SIZE; i++) {
        q->data[i] = 0;
    }
}

// ------------------------- 打印队列 -------------------------

/**
 * @brief 打印当前队列中所有有效元素（从 front → rear）
 * @param q 指向队列的指针
 */
void printQueue(circleQueue *q) {
    if (isEmpty(q)) return;

    int i = q->front;
    while (i != q->rear) {
        printf("value is %d\n", q->data[i]);
        i = (i + 1) % MAX_SIZE;
    }
    printf("\n");
}

// ------------------------- 主函数测试 -------------------------

/**
 * @brief 测试循环队列的基本功能
 */
int main() {
    circleQueue q;
    initCircleQueue(&q);             // 初始化队列

    inQueue(&q, 1);
    inQueue(&q, 2);
    inQueue(&q, 3);
    clearQueue(&q);
    printQueue(&q);

    // printQueue(&q);                  // 输出：1 2 3
    //
    // int deValue;
    // deQueue(&q, &deValue);          // 出队一个元素（1）
    //
    // printQueue(&q);                 // 输出：2 3
    //
    // int topValue;
    // peek(&q, &topValue);            // 查看队头元素（2）
    // printf("top value is %d\n", topValue);

    return 0;
}
